﻿using System;
using WiMo.Games;
using WiMo.Games.Drawables;
using WiMo.Games.Inputs;
using WiMo.Games.StandardMenus;
using WiMo.Games.Menus;

namespace Collisions
{
    class Game : IGame
    {
        private const string STR_DIAG = "DIAG";
        private const int INT_RESUME = 100;
        private const int INT_EXPLODE = 101;
        private const int INT_NUMBERBALLS = 102;
        private const int INT_RENDERQUALITY = 103;
        private const int INT_DIAGNOSTICS = 104;
        private const int INT_EXIST = 105;
        private const string STR_RENDER_QUALITY = "RENDER_QUALITY";
        private const string STR_FAST = "Fast";
        private const string STR_QUALITY = "Quality";

        ISpriteImage[] _balls;
        ISpriteImage _backgroudImage;
        IMenuComponent _mainMenu;
        IMenu _ballCount;
        IMenu mnuRenderQuality;
        int numbBalls = 256;
        int currentNumberBalls;
        string renderQuality;

        public Game(IGameEngine engine)
        {
            Engine = engine;
            Engine.ContentManager.ContentLocation = "Content";
            Engine.Display.BackgroundColor = Color.CornFlowerBlue;
            Engine.Display.DisplayStrategy = DisplayStrategies.MostlyDynamic;
            Engine.EnableDiagnostics = false;
            Engine.DiagnosticsFontColor = Color.White;
        }

        public void Initialize()
        {
            Engine.PhysicsManager.Gravity = new Vector2(0, 10);
        }

        public void BeginRun() 
        {
            SetVisibleBalls();        
            Engine.EnableDiagnostics = Convert.ToBoolean(Engine.StateManager.Get(STR_DIAG,"true"));
        }

        public void CreateMenus()
        {
            currentNumberBalls = Convert.ToInt32(Engine.StateManager.Get("NUMBER_BALLS", "16"));
            renderQuality = Engine.StateManager.Get(STR_RENDER_QUALITY, STR_FAST);
            renderQuality = STR_QUALITY;

            Engine.InputManager.SoftMenuFontColor = Color.White;
            Engine.InputManager.UseAccelerometerAsThumbPad = true;
            Engine.InputManager.RightSoftButton = "Exit";
            Engine.InputManager.LeftSoftButton = "Menu";
            Engine.InputManager.MenuBarBackgroundColor = new Color(Color.Black, 0x7f);

            _mainMenu = Engine.MenuManager.Create("Main Menu");
            _mainMenu.MenuSelected += new EventHandler<SelectedMenuEventArgs>(_mainMenu_MenuSelected);
            _mainMenu.AddMenu("Resume", INT_RESUME);
            _mainMenu.AddMenu("Explode!", INT_EXPLODE);
            _ballCount = _mainMenu.AddMenu(string.Format("Number Balls: {0}", currentNumberBalls), INT_NUMBERBALLS);
            mnuRenderQuality = _mainMenu.AddMenu(string.Format("Render Quality: {0}", renderQuality),INT_RENDERQUALITY);

            _mainMenu.AddMenu("Diagnostics",INT_DIAGNOSTICS);
            _mainMenu.AddMenu("Exit", INT_EXIST);

            Engine.Components.Add(_mainMenu);            
        }

        public void LoadContent()
        {
            _backgroudImage = Engine.ContentManager.LoadImage("Background");
            _balls = new ISpriteImage[numbBalls];

            var top = 30;
            var left = 10;

            for (int idx = 0; idx < numbBalls; ++idx)
            {
                ISpriteImage ball = Engine.ContentManager.LoadImage(string.Format("Ball{0}", (idx % 5) + 1));
                left += ball.UnscaledSize.Width + 2;
                if (left > Engine.Display.TargetSize.Width)
                {
                    top += 20;
                    left = 10;
                }

                ball.Origin = Origin.Center;
                ball.Position = new PointF(left, top);
                ball.Force = new Vector2(32 - Engine.Randomizer.Next(64), 32 - Engine.Randomizer.Next(64));
                ball.AffectedByGravity = false;
                ball.CollisionShape = CollisionShapes.Sphere;
                ball.ColorKey = Color.White;
                ball.IsStatic = false;
                ball.CoefRestitution = 0.75f;
                ball.RenderStrategy = RenderStrategy.Quality;
                //ball.CollisionCategory = CollisionCategory.One;
                //ball.CanCollidesWithList.Add(CollisionCategory.One);
                ball.Collision += ball_Collision;
                ball.CollisionManagement = CollisionManagement.Auto;
                Engine.PhysicsManager.Add(ball);
                Engine.CollisionManager.Add(ball);

                _balls[idx] = ball;
            }
        }

        void Explode()
        {
            var center = new PointF(Engine.Display.TargetSize.Width /2, Engine.Display.TargetSize.Height / 2);

            for (var idx = 0; idx < currentNumberBalls; ++idx)
            {
                _balls[idx].Position = center;
                _balls[idx].Force = new Vector2(128 - Engine.Randomizer.Next(256), 128 - Engine.Randomizer.Next(256));
            }
        }

        void SetVisibleBalls()
        {
            _ballCount.Text = string.Format(string.Format("Number Balls: {0}", currentNumberBalls));

            foreach (var ball in _balls)
            {
                ball.IsVisible = false;
                ball.IsStatic = true;
                switch (renderQuality)
                {
                    case STR_FAST:
                        ball.RenderStrategy = RenderStrategy.Fast;
                        break;
                    case STR_QUALITY:
                        ball.RenderStrategy = RenderStrategy.Quality;
                        break;
                }
            }

            for (var idx = 0; idx < currentNumberBalls; ++idx)
            {
                _balls[idx].IsVisible = true;
                _balls[idx].IsStatic = false;
            }
        }

        void _mainMenu_MenuSelected(object sender, SelectedMenuEventArgs e)
        {
            switch (e.SelectedMenu.MenuId)
            {
                case INT_RESUME:
                    _mainMenu.Hide();

                    break;
                case INT_EXPLODE:
                    _mainMenu.Hide();
                    Explode();
                    break;
                case INT_NUMBERBALLS:
                    currentNumberBalls *= 2;
                    if (currentNumberBalls > 256)
                        currentNumberBalls = 16;

                    Engine.StateManager.Store("NUMBER_BALLS", currentNumberBalls.ToString());
                    SetVisibleBalls();
                    break;
                case INT_RENDERQUALITY:
                    switch (renderQuality)
                    {
                        case STR_FAST:
                            renderQuality = STR_QUALITY;
                            break;
                        case STR_QUALITY:
                            renderQuality = STR_FAST;
                            break;
                    }
                    mnuRenderQuality.Text = string.Format("Render Quality: {0}", renderQuality);
                    Engine.StateManager.Store(STR_RENDER_QUALITY, renderQuality);
                    SetVisibleBalls();
                    
                    break;
                case INT_DIAGNOSTICS:
                    Engine.EnableDiagnostics = !Engine.EnableDiagnostics;
                    Engine.StateManager.Store(STR_DIAG, Engine.EnableDiagnostics.ToString());
                    break;
                case INT_EXIST:
                    Engine.Exit();
                    break;
            }
        }
       

        void ball_Collision(object sender, CollisionEventArgs e)
        {
            //            if(e.CollisionType == CollisionEventArgs.CollisionTypes.Border)
            //                Engine.Vibrate(20);
        }

        private IInputManager _lastState;

        public void Update(WiMo.Games.GameTime gameTime)
        {
            if (Engine.InputManager.IsKeyDown(Keys.Return))
                Engine.Exit();

            if (Engine.InputManager.IsKeyDown(Keys.RightSoftButton))
                Engine.Exit();

            if (Engine.InputManager.WasPressed(_lastState, Keys.LeftSoftButton))
                _mainMenu.Show();

            if (Engine.InputManager.IsKeyDown(Keys.Left))
            {
                foreach (var ball in _balls)
                    ball.Force = new Vector2(ball.Force.X - 3, ball.Force.Y);
            }

            if (Engine.InputManager.IsKeyDown(Keys.Right))
            {
                foreach (var ball in _balls)
                    ball.Force = new Vector2(ball.Force.X + 3, ball.Force.Y);
            }

            if (Engine.InputManager.IsKeyDown(Keys.Down))
            {
                foreach (var ball in _balls)
                    ball.Force = new Vector2(ball.Force.X, ball.Force.Y + 3);
            }

            if (Engine.InputManager.IsKeyDown(Keys.Up))
            {
                foreach (var ball in _balls)
                    ball.Force = new Vector2(ball.Force.X, ball.Force.Y - 3);
            }

            _lastState = Engine.InputManager.GetKeysState();
        }

        public void Draw(WiMo.Games.GameTime gameTime)
        {
            Engine.Display.BackgroundImage = _backgroudImage.TextureList[_backgroudImage.ImageIndex];

            foreach (var ball in _balls)
                if (ball.IsVisible)
                    Engine.Display.Add(ball);
        }

        public bool CanExit()
        {
            return true;
        }

        public WiMo.Games.IGameEngine Engine { get; set; }
    }
}
